package com.zsk.shop.service;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.zsk.shop.common.base.BaseResponse;
import com.zsk.shop.common.base.model.token.UserSimple;
import com.zsk.shop.common.constant.Constant;
import com.zsk.shop.common.enums.EnumType;
import com.zsk.shop.common.socket.ServicePushSocketServer;
import com.zsk.shop.common.utils.EntityConvertUtils;
import com.zsk.shop.common.utils.HttpContext;
import com.zsk.shop.common.utils.TokenUtil;
import com.zsk.shop.common.utils.ToolUtil;
import com.zsk.shop.entity.ShopUser;
import com.zsk.shop.entity.TokenInfo;
import com.zsk.shop.enums.EnumGenderType;
import com.zsk.shop.model.results.AppUserDecodeResult;
import com.zsk.shop.model.results.LoginUserResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ljh
 */
@Service
@DS("master")
public class BaseService {

    private final static Logger logger = LoggerFactory.getLogger(BaseService.class);

    @Autowired
    private Environment environment;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private TokenInfoService tokenInfoService;

    @Autowired
    private ServicePushSocketServer servicePushSocketServer;

    /**
     * OSS获取令牌
     *
     * @return
     * @throws ClientException
     */
    public BaseResponse<Map<String, String>> createParameters() throws ClientException {
        String endpoint = environment.getProperty("ali.stsRAM.endpoint");
        String accessKeyId = environment.getProperty("ali.stsRAM.accessKeyId");
        String accessKeySecret = environment.getProperty("ali.stsRAM.accessKeySecret");
        String roleArn = environment.getProperty("ali.stsRAM.roleArn");
        String roleSessionName = ToolUtil.isEmpty(HttpContext.getSafeUserNo()) ? "AA202102181025001" : HttpContext.getSafeUserNo();
        //{"Version":"1","Statement":[{"Action":["oss:*"],"Resource":["acs:oss:*:*:*"],"Effect":"Allow"}]}
        String policy = "{\"Version\":\"1\",\"Statement\":[{\"Action\":[\"oss:*\"],\"Resource\":[\"acs:oss:*:*:*\"],\"Effect\":\"Allow\"}]}";
        Map<String, String> map = new HashMap<>();
        try {
            // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
            DefaultProfile.addEndpoint("", "ap-southeast-1", "Sts", endpoint);
            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("ap-southeast-1", accessKeyId, accessKeySecret);
            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            // Optional
            request.setPolicy(policy);
            // 设置凭证有效时间
            request.setDurationSeconds(1000L);
            // 必须使用HTTPS协议访问STS服务);
            request.setProtocol(ProtocolType.HTTPS);
            final AssumeRoleResponse response = client.getAcsResponse(request);
            map.put("Expiration", response.getCredentials().getExpiration());
            map.put("AccessKeyId", response.getCredentials().getAccessKeyId());
            map.put("AccessKeySecret", response.getCredentials().getAccessKeySecret());
            map.put("SecurityToken", response.getCredentials().getSecurityToken());
            map.put("endPoint", "http://oss-ap-southeast-1.aliyuncs.com/");
            map.put("bucketName", "zhishangke");
            map.put("url", "https://oss.zhishangkeapp.com/");
            return BaseResponse.success(map);
        } catch (ClientException e) {
            System.out.println("Failed：");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());
        }
        return BaseResponse.success(null);
    }

    public AppUserDecodeResult getDecodeResult(ShopUser user) {
        AppUserDecodeResult decodeResult = new AppUserDecodeResult();
        UserSimple userSimple = EntityConvertUtils.convertAToB(user, UserSimple.class);
        decodeResult.setHavePwd(ToolUtil.isNotEmpty(user.getPassword()) ? true : false);
        decodeResult.setHavePhone(ToolUtil.isNotEmpty(user.getPhone()) ? true : false);
        decodeResult.setToken(this.getUserTokenHave(userSimple));
        decodeResult.setUserResult(EntityConvertUtils.convertAToB(user, LoginUserResult.class));
        return decodeResult;
    }

    /**
     * 判断是否重新获得token获取新token
     *
     * @param userSimple 当前用户的新的精简体
     * @return
     */
    public String getUserTokenHave(UserSimple userSimple) {
        //TOKEN_INFO中是否有可用的值
        Long userId = userSimple.getId();
        List<TokenInfo> tokenInfoList = tokenInfoService.queryUnInvalidTokensByUserId(userId, userSimple.getUserType(), null);
        if (ToolUtil.isNotEmpty(tokenInfoList)) {
//            return tokenInfoList.get(0).getToken();
            servicePushSocketServer.clearUserInfoByUserNo(userId, userSimple.getUserNo(), userSimple.getUserType(), false);
            return tokenUtil.genToken(userSimple, null);
        } else {
            servicePushSocketServer.clearUserInfoByUserNo(userId, userSimple.getUserNo(), userSimple.getUserType(), false);
            //处理tokenInfo中其他过期的即可，也可以不做处理
            return tokenUtil.genToken(userSimple, null);
        }
    }

    public BaseResponse<EnumType> genderList() {
        return BaseResponse.success(EnumGenderType.getList());
    }

    public static String encode(String data) {
        //把字符串转为字节数组
        byte[] b = data.getBytes();
        //遍历
        for (int i = 0; i < b.length; i++) {
            b[i] += 1;//在原有的基础上+1
        }
        return new String(b);
    }

    /**
     * 解密：把一个加密后的字符串在原有基础上-1
     *
     * @param data 加密后的字符串
     * @return 返回解密后的新字符串
     */
    public static String decode(String data) {
        //把字符串转为字节数组
        byte[] b = data.getBytes();
        //遍历
        for (int i = 0; i < b.length; i++) {
            b[i] -= 1;//在原有的基础上-1
        }
        return new String(b);
    }
}
